included hddtemp code for SCSI disk temperatures

This commit is contained in:
Gerold Gruber
2023-10-10 14:01:20 +02:00
parent 525cf037c5
commit 3bc3de37ae
10 changed files with 749 additions and 26 deletions

View File

@@ -6,5 +6,5 @@ AM_LDFLAGS =
# this lists the binaries to produce, the (non-PHONY, binary) targets in
# the previous manual Makefile
bin_PROGRAMS = nwipe
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c
nwipe_SOURCES = context.h logging.h options.h prng.h version.h temperature.h nwipe.c gui.c method.h pass.c device.c gui.h isaac_rand/isaac_standard.h isaac_rand/isaac_rand.h isaac_rand/isaac_rand.c isaac_rand/isaac64.h isaac_rand/isaac64.c mt19937ar-cok/mt19937ar-cok.c nwipe.h mt19937ar-cok/mt19937ar-cok.h pass.h device.h logging.c method.c options.c prng.c version.c temperature.c PDFGen/pdfgen.h PDFGen/pdfgen.c create_pdf.c create_pdf.h embedded_images/shred_db.jpg.c embedded_images/shred_db.jpg.h embedded_images/tick_erased.jpg.c embedded_images/tick_erased.jpg.h embedded_images/redcross.c embedded_images/redcross.h hpa_dco.h hpa_dco.c miscellaneous.h miscellaneous.c embedded_images/nwipe_exclamation.jpg.h embedded_images/nwipe_exclamation.jpg.c conf.h conf.c customers.h customers.c hddtemp_scsi/hddtemp.h hddtemp_scsi/scsi.h hddtemp_scsi/scsicmds.h hddtemp_scsi/get_scsi_temp.c hddtemp_scsi/scsi.c hddtemp_scsi/scsicmds.c
nwipe_LDADD = $(PARTED_LIBS) $(LIBCONFIG)

View File

@@ -24,6 +24,9 @@
#define CONTEXT_H_
#include "prng.h"
#ifndef __HDDTEMP_H__
#include "hddtemp_scsi/hddtemp.h"
#endif /* __HDDTEMP_H__ */
typedef enum nwipe_device_t_ {
NWIPE_DEVICE_UNKNOWN = 0, // Unknown device.
@@ -133,6 +136,8 @@ typedef struct nwipe_context_t_
u64 throughput; // Average throughput in bytes per second.
char throughput_txt[13]; // Human readable throughput.
u64 verify_errors; // The number of verification errors across all passes.
int templ_has_hwmon_data; // 0 = no hwmon data available, 1 = hwmon data available
int templ_has_scsitemp_data; // 0 = no scsitemp data available, 1 = scsitemp data available
char temp1_path[MAX_HWMON_PATH_LENGTH]; // path to temperature variables /sys/class/hwmon/hwmonX/ etc.
int temp1_crit; // Critical high drive temperature, 1000000=unitialised, millidegree celsius.
int temp1_highest; // Historical highest temperature reached, 1000000=unitialised, millidegree celsius.
@@ -148,6 +153,7 @@ typedef struct nwipe_context_t_
int temp1_flash_rate_counter; // used by the gui for timing the flash rate
int temp1_flash_rate_status; // 0=blank 1=visible
time_t temp1_time; // The time when temperature was last checked, seconds since epoch
struct disk* templ_disk; // Pointer to disk structure for hddtemp SCSI routines
int wipe_status; // Wipe finished = 0, wipe in progress = 1, wipe yet to start = -1.
char wipe_status_txt[10]; // ERASED, FAILED, ABORTED, INSANITY
int spinner_idx; // Index into the spinner character array

View File

@@ -0,0 +1,137 @@
/*
* get_scsi_temp.c: functions that populate the drive temperature variables
* in SCSI/SAS drives context structure.
* Routines from hddtemp are used here.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
//#define _LARGEFILE64_SOURCE
//#define _FILE_OFFSET_BITS 64
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <dirent.h>
#include <assert.h>
#include "nwipe.h"
#include "context.h"
#include "method.h"
#include "device.h"
#include "prng.h"
#include "options.h"
#include "device.h"
#include "logging.h"
#include "temperature.h"
#include "miscellaneous.h"
#include "hddtemp.h"
#include "scsi.h"
int nwipe_init_scsi_temperature( nwipe_context_t* c )
{
/* dsk anlegen, malloc */
struct disk *dsk = (struct disk *) malloc(sizeof(struct disk));
/* Check the allocation. */
if( !dsk )
{
nwipe_perror( errno, __FUNCTION__, "malloc" );
nwipe_log( NWIPE_LOG_FATAL, "Unable to get memory for disk struct for %s",
c->device_name );
exit( 1 ) ;
}
assert(dsk);
memset(dsk, 0, sizeof(*dsk));
/* save the dsk pointer for later use */
c->templ_disk = dsk;
/* initialize */
dsk->drive = c->device_name;
dsk->type = BUS_SCSI; /* we know this as we are only called in this case */
errno = 0;
dsk->errormsg[0] = '\0';
if( (dsk->fd = open(dsk->drive, O_RDONLY | O_NONBLOCK)) < 0) {
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, "open: %s\n", strerror(errno));
dsk->type = ERROR;
return 1;
}
// sg_logs -t <device>
if( scsi_get_temperature( dsk ) == GETTEMP_SUCCESS )
{
c->temp1_input = dsk->value;
c->temp1_crit = dsk->refvalue;
}
else
{
nwipe_log( NWIPE_LOG_ERROR, "Can not read SCSI temperature for %s, %s",
dsk->drive, dsk->errormsg );
free( dsk );
c->templ_disk = NULL;
return 1;
}
return 0;
}
int nwipe_get_scsi_temperature( nwipe_context_t* c )
{
struct disk *dsk;
dsk = c->templ_disk;
if( c->templ_disk != NULL && c->templ_disk->fd != -1 )
{
if( scsi_get_temperature( dsk ) == GETTEMP_SUCCESS )
{
c->temp1_input = dsk->value;
}
else
{
nwipe_log( NWIPE_LOG_ERROR, "Could not read SCSI temperature for %s, %s",
dsk->drive, dsk->errormsg );
return 2;
}
}
else
{
nwipe_log( NWIPE_LOG_INFO, "no SCSI temperature reading for %s", dsk->drive );
return 1;
}
return 0;
}
void nwipe_shut_scsi_temperature( nwipe_context_t* c )
{
if( c->templ_disk->fd != -1 )
{
close( c->templ_disk->fd );
}
if( c->templ_disk != NULL )
{
free( c->templ_disk );
}
return;
}

102
src/hddtemp_scsi/hddtemp.h Normal file
View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __HDDTEMP_H__
#define __HDDTEMP_H__
#include <time.h>
// #include "db.h"
//#ifdef ARCH_I386
//typedef unsigned short u16;
//#endif
#include <linux/types.h>
typedef __u16 u16;
#define MAX_ERRORMSG_SIZE 128
#define DEFAULT_ATTRIBUTE_ID 194
#define F_to_C(val) (int)(((double)(val)-32.0)/1.8)
#define C_to_F(val) (int)(((double)(val)*(double)1.8) + (double)32.0)
enum e_bustype { ERROR = 0, BUS_UNKNOWN, BUS_SATA, BUS_ATA, BUS_SCSI, BUS_TYPE_MAX };
// enum e_gettemp {
// GETTEMP_ERROR, /* Error */
// GETTEMP_NOT_APPLICABLE, /* */
// GETTEMP_UNKNOWN, /* Drive is not in database */
// GETTEMP_GUESS, /* Not in database, but something was guessed, user must
// check that the temperature returned is correct */
// GETTEMP_KNOWN, /* Drive appear in database */
// GETTEMP_NOSENSOR, /* Drive appear in database but is known to have no sensor */
// GETTEMP_DRIVE_SLEEP, /* Drive is sleeping */
// GETTEMP_SUCCESS /* read temperature successfully */
// };
#define GETTEMP_SUCCESS 0
#define GETTEMP_ERROR 1
#define GETTEMP_NOT_APPLICABLE 2
#define GETTEMP_UNKNOWN 3
#define GETTEMP_GUESS 4
#define GETTEMP_KNOWN 5
#define GETTEMP_NOSENSOR 6
#define GETTEMP_DRIVE_SLEEP 7
enum e_powermode {
PWM_UNKNOWN,
PWM_ACTIVE,
PWM_SLEEPING,
PWM_STANDBY
};
struct disk {
struct disk * next;
int fd;
const char * drive;
const char * model;
enum e_bustype type;
int value; /* the drive's temperature */
int refvalue; /* aka trip temperature */
struct harddrive_entry * db_entry;
char errormsg[MAX_ERRORMSG_SIZE];
// enum e_gettemp ret;
int ret;
time_t last_time;
};
struct bustype {
char *name;
int (*probe)(int);
const char *(*model)(int);
enum e_gettemp (*get_temperature)(struct disk *);
};
extern struct bustype * bus[BUS_TYPE_MAX];
extern char errormsg[MAX_ERRORMSG_SIZE];
extern int tcp_daemon, debug, quiet, wakeup, af_hint;
extern char separator;
extern long portnum, syslog_interval;
extern char * listen_addr;
int value_to_unit(struct disk *dsk);
char get_unit(struct disk *dsk);
#endif

153
src/hddtemp_scsi/scsi.c Normal file
View File

@@ -0,0 +1,153 @@
/*
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Adapted from a patch sended by : Frederic LOCHON <lochon@roulaise.net>
*/
// Include file generated by ./configure
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
// Gettext includes
#if ENABLE_NLS
#include <libintl.h>
#define _(String) gettext (String)
#else
#define _(String) (String)
#endif
// Standard includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <scsi/scsi.h>
// Application specific includes
#include "scsicmds.h"
#include "hddtemp.h"
/*
static int scsi_probe(int device) {
int bus_num;
if(ioctl(device, SCSI_IOCTL_GET_BUS_NUMBER, &bus_num))
return 0;
else
return 1;
}
static const char *scsi_model (int device) {
unsigned char buf[36];
if (scsi_inquiry(device, buf) != 0)
return strdup(_("unknown"));
else {
return strdup(buf + 8);
}
}
*/
int scsi_get_temperature(struct disk *dsk) {
int i;
int tempPage = 0;
unsigned char buffer[1024];
/*
on triche un peu
we cheat a little and do not really read form drivedb as SCSI disks are not included there
*/
// dsk->db_entry = (struct harddrive_entry*) malloc(sizeof(struct harddrive_entry));
// if(dsk->db_entry == NULL) {
// perror("malloc");
// exit(-1);
// }
//
// dsk->db_entry->regexp = "";
// dsk->db_entry->description = "";
// dsk->db_entry->attribute_id = 0;
// dsk->db_entry->unit = 'C';
// dsk->db_entry->next = NULL;
//
// if (scsi_smartsupport(dsk->fd) == 0) {
// snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("S.M.A.R.T. not available"));
// close(dsk->fd);
// dsk->fd = -1;
// return GETTEMP_NOT_APPLICABLE;
// }
//
/*
Enable SMART
*/
if (scsi_smartDEXCPTdisable(dsk->fd) != 0) {
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, "%s", strerror(errno));
close(dsk->fd);
dsk->fd = -1;
return GETTEMP_ERROR;
}
/*
Temp. capable
*/
if (scsi_logsense(dsk->fd , SUPPORT_LOG_PAGES, buffer, sizeof(buffer)) != 0) {
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("log sense failed : %s"), strerror(errno));
close(dsk->fd);
dsk->fd = -1;
return GETTEMP_ERROR;
}
for ( i = 4; i < buffer[3] + LOGPAGEHDRSIZE ; i++) {
if (buffer[i] == TEMPERATURE_PAGE) {
tempPage = 1;
break;
}
}
if(tempPage) {
/*
get temperature (from scsiGetTemp (scsicmd.c))
*/
if (scsi_logsense(dsk->fd , TEMPERATURE_PAGE, buffer, sizeof(buffer)) != 0) {
snprintf(dsk->errormsg, MAX_ERRORMSG_SIZE, _("log sense failed : %s"), strerror(errno));
close(dsk->fd);
dsk->fd = -1;
return GETTEMP_ERROR;
}
dsk->value = buffer[9];
dsk->refvalue = buffer[15];
return GETTEMP_SUCCESS;
} else {
return GETTEMP_NOSENSOR;
}
}
/*******************************
*******************************/
/*
struct bustype scsi_bus = {
"SCSI",
scsi_probe,
scsi_model,
scsi_get_temperature
};
*/

24
src/hddtemp_scsi/scsi.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SCSIC_H_
#define SCSIC_H_
extern struct bustype scsi_bus;
#endif

221
src/hddtemp_scsi/scsicmds.c Normal file
View File

@@ -0,0 +1,221 @@
/*
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// Include file generated by ./configure
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
// Gettext includes
#if ENABLE_NLS
#include <libintl.h>
#define _(String) gettext (String)
#else
#define _(String) (String)
#endif
// Standard includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <scsi/scsi_ioctl.h>
// Application specific includes
#include "scsicmds.h"
static void scsi_fixstring(unsigned char *s, int bytecount)
{
unsigned char *p;
unsigned char *end;
p = s;
end = s + bytecount;
/* strip leading blanks */
while (s != end && *s == ' ')
++s;
/* compress internal blanks and strip trailing blanks */
while (s != end && *s) {
if (*s++ != ' ' || (s != end && *s && *s != ' '))
*p++ = *(s-1);
}
/* wipe out trailing garbage */
while (p != end)
*p++ = '\0';
}
int scsi_SG_IO(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, unsigned char *sense, unsigned char sense_len, int dxfer_direction) {
struct sg_io_hdr io_hdr;
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
io_hdr.interface_id = 'S';
io_hdr.cmdp = cdb;
io_hdr.cmd_len = cdb_len;
io_hdr.dxfer_len = buffer_len;
io_hdr.dxferp = buffer;
io_hdr.mx_sb_len = sense_len;
io_hdr.sbp = sense;
io_hdr.dxfer_direction = dxfer_direction;
io_hdr.timeout = 3000; /* 3 seconds should be ample */
return ioctl(device, SG_IO, &io_hdr);
}
int scsi_SEND_COMMAND(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, int dxfer_direction)
{
unsigned char buf[2048];
unsigned int inbufsize, outbufsize, ret;
switch(dxfer_direction) {
case SG_DXFER_FROM_DEV:
inbufsize = 0;
outbufsize = buffer_len;
break;
case SG_DXFER_TO_DEV:
inbufsize = buffer_len;
outbufsize = 0;
break;
default:
inbufsize = 0;
outbufsize = 0;
break;
}
memcpy(buf, &inbufsize , sizeof(inbufsize));
memcpy(buf + sizeof(inbufsize), &outbufsize , sizeof(outbufsize));
memcpy(buf + sizeof(inbufsize) + sizeof(outbufsize), cdb, cdb_len);
memcpy(buf + sizeof(inbufsize) + sizeof(outbufsize) + cdb_len, buffer, buffer_len);
ret = ioctl(device, SCSI_IOCTL_SEND_COMMAND, buf);
memcpy(buffer, buf + sizeof(inbufsize) + sizeof(outbufsize), buffer_len);
return ret;
}
int scsi_command(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, int dxfer_direction)
{
static int SG_IO_supported = -1;
int ret;
if (SG_IO_supported == 1)
return scsi_SG_IO(device, cdb, cdb_len, buffer, buffer_len, NULL, 0, dxfer_direction);
else if (SG_IO_supported == 0)
return scsi_SEND_COMMAND(device, cdb, cdb_len, buffer, buffer_len, dxfer_direction);
else {
ret = scsi_SG_IO(device, cdb, cdb_len, buffer, buffer_len, NULL, 0, dxfer_direction);
if (ret == 0) {
SG_IO_supported = 1;
return ret;
} else {
SG_IO_supported = 0;
return scsi_SEND_COMMAND(device, cdb, cdb_len, buffer, buffer_len, dxfer_direction);
}
}
}
int scsi_inquiry(int device, unsigned char *buffer)
{
unsigned char cdb[6];
memset(cdb, 0, sizeof(cdb));
cdb[0] = INQUIRY;
cdb[4] = 36; /* should be 36 for unsafe devices (like USB mass storage stuff)
* otherwise they can lock up! SPC sections 7.4 and 8.6 */
if (scsi_command(device, cdb, sizeof(cdb), buffer, cdb[4], SG_DXFER_FROM_DEV) != 0)
return 1;
else {
scsi_fixstring(buffer + 8, 24);
return 0;
}
}
int scsi_modesense(int device, unsigned char pagenum, unsigned char *buffer, int buffer_len) {
unsigned char cdb[6];
int ret;
memset(cdb, 0, sizeof(cdb));
cdb[0] = MODE_SENSE;
cdb[2] = pagenum;
cdb[4] = 0xff;
ret = scsi_command(device, cdb, sizeof(cdb), buffer, buffer_len, SG_DXFER_FROM_DEV);
if (ret == 0) {
if ((buffer[3] + 5) > buffer[0]) /* response length too short */
return -1;
}
return ret;
}
int scsi_modeselect(int device, char *buffer) {
unsigned char cdb[6];
memset(cdb, 0, sizeof(cdb));
cdb[0] = MODE_SELECT;
cdb[1] = 0x11;
cdb[4] = buffer[0] + 1;
memset(buffer, 0, 12);
buffer[3] = 0x08;
buffer[10] = 0x02;
buffer[12] &= 0x3f;
return scsi_command(device, cdb, sizeof(cdb), buffer, cdb[4], SG_DXFER_TO_DEV);
}
int scsi_logsense(int device, int pagenum, unsigned char *buffer, int buffer_len) {
unsigned char cdb[10];
memset(cdb, 0, sizeof(cdb));
cdb[0] = LOG_SENSE;
cdb[2] = 0x40 | pagenum;
cdb[7] = 0x04;
return scsi_command(device, cdb, sizeof(cdb), buffer, buffer_len, SG_DXFER_FROM_DEV);
}
int scsi_smartsupport(int device) {
unsigned char buf[255];
if (scsi_modesense (device, EXCEPTIONS_CONTROL_PAGE, buf, sizeof(buf)) != 0)
return 0;
else
return (buf[14] & 0x08) == 0;
}
int scsi_smartDEXCPTdisable(int device) {
unsigned char buf[255];
if (scsi_modesense (device, EXCEPTIONS_CONTROL_PAGE, buf, sizeof(buf)) != 0)
return 1;
if (buf[14] & 0x08) {
buf[14] &= 0xf7;
buf[15] = 0x04;
return scsi_modeselect (device, buf);
}
else
return 0;
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2002 Emmanuel VARAGNAT <hddtemp@guzu.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SCSICMDS_H_
#define SCSICMDS_H_
#define SUPPORT_LOG_PAGES 0x00
#define TEMPERATURE_PAGE 0x0d
#define EXCEPTIONS_CONTROL_PAGE 0x1c
#define LOGPAGEHDRSIZE 4
int scsi_SG_IO(int device, unsigned char *cdb, int cdb_len, unsigned char *buffer, int buffer_len, unsigned char *sense, unsigned char sense_len, int dxfer_direction);
int scsi_inquiry(int device, unsigned char *buffer);
int scsi_modesense(int device, unsigned char pagenum, unsigned char *buffer, int buffer_len);
int scsi_modeselect(int device, char *buffer);
int scsi_logsense(int device, int pagenum, unsigned char *buffer, int buffer_len);
int scsi_smartsupport(int device);
int scsi_smartDEXCPTdisable(int device);
#endif

View File

@@ -59,6 +59,7 @@ int nwipe_init_temperature( nwipe_context_t* c )
* so it can display appropriate information when a
* device is unable to provide temperature data */
c->templ_has_hwmon_data = 0;
c->temp1_crit = NO_TEMPERATURE_DATA;
c->temp1_highest = NO_TEMPERATURE_DATA;
c->temp1_input = NO_TEMPERATURE_DATA;
@@ -187,6 +188,7 @@ int nwipe_init_temperature( nwipe_context_t* c )
}
/* Copy the hwmon path to the drive context structure */
strcpy( c->temp1_path, dirpath_hwmonX );
c->templ_has_hwmon_data = 1;
}
}
closedir( dir2 );
@@ -195,6 +197,20 @@ int nwipe_init_temperature( nwipe_context_t* c )
}
closedir( dir );
}
/* if no hwmon data available try scsi access (SAS Disks are known to be not working in hwmon */
if( c->templ_has_hwmon_data == 0 && ( c->device_type == NWIPE_DEVICE_SAS || c->device_type == NWIPE_DEVICE_SCSI ) )
{
nwipe_log( NWIPE_LOG_NOTICE, "no hwmon data for %s, try to get SCSI data", c->device_name );
if( nwipe_init_scsi_temperature( c ) == 0 )
{
c->templ_has_scsitemp_data = 1;
nwipe_log( NWIPE_LOG_INFO, "got SCSI temperature data for %s", c->device_name );
}
{
c->templ_has_scsitemp_data = 0;
nwipe_log( NWIPE_LOG_INFO, "got no SCSI temperature data for %s", c->device_name );
}
}
return 0;
}
@@ -224,37 +240,56 @@ void nwipe_update_temperature( nwipe_context_t* c )
int idx;
int result;
for( idx = 0; idx < NUMBER_OF_FILES; idx++ )
/* try to get temperatures from hwmon, standard */
if( c->templ_has_hwmon_data == 1 )
{
/* Construct the full path including filename */
strcpy( path, c->temp1_path );
strcat( path, "/" );
strcat( path, &( temperature_label[idx][0] ) );
/* Open the file */
if( ( fptr = fopen( path, "r" ) ) != NULL )
for( idx = 0; idx < NUMBER_OF_FILES; idx++ )
{
/* Acquire data until we reach a newline */
result = fscanf( fptr, "%[^\n]", temperature );
/* Construct the full path including filename */
strcpy( path, c->temp1_path );
strcat( path, "/" );
strcat( path, &( temperature_label[idx][0] ) );
/* Convert numeric ascii to binary integer */
*( temperature_pcontext[idx] ) = atoi( temperature );
/* Divide by 1000 to get degrees celsius */
*( temperature_pcontext[idx] ) = *( temperature_pcontext[idx] ) / 1000;
if( nwipe_options.verbose )
/* Open the file */
if( ( fptr = fopen( path, "r" ) ) != NULL )
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s %dC", path, *( temperature_pcontext[idx] ) );
/* Acquire data until we reach a newline */
result = fscanf( fptr, "%[^\n]", temperature );
/* Convert numeric ascii to binary integer */
*( temperature_pcontext[idx] ) = atoi( temperature );
/* Divide by 1000 to get degrees celsius */
*( temperature_pcontext[idx] ) = *( temperature_pcontext[idx] ) / 1000;
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: %s %dC", path, *( temperature_pcontext[idx] ) );
}
fclose( fptr );
}
fclose( fptr );
}
else
{
if( nwipe_options.verbose )
else
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path );
if( nwipe_options.verbose )
{
nwipe_log( NWIPE_LOG_NOTICE, "hwmon: Unable to open %s", path );
}
}
}
}
else
{
/* alternative method to get temperature from SCSI/SAS disks */
if( c->device_type == NWIPE_DEVICE_SAS || c->device_type == NWIPE_DEVICE_SCSI )
{
if( c->templ_has_scsitemp_data == 1 )
{
nwipe_log( NWIPE_LOG_NOTICE, "hddtemp: get temperature for %s", c->device_name );
if( nwipe_get_scsi_temperature( c ) != 0 )
{
nwipe_log( NWIPE_LOG_ERROR, "get_scsi_temperature error" );
}
}
}
}

View File

@@ -35,6 +35,15 @@ int nwipe_init_temperature( nwipe_context_t* );
void nwipe_update_temperature( nwipe_context_t* );
/**
* Workaround for obtaining temperatures from SCSI/SAS drives
* @param pointer to a drive context
* @return returns 0 on success < 1 on error
*/
int nwipe_init_scsi_temperature( nwipe_context_t* );
int nwipe_get_scsi_temperature( nwipe_context_t* );
void nwipe_shut_scsi_temperature( nwipe_context_t* );
/**
* This function is normally called only once. It's called after both the
* nwipe_init_temperature() function and nwipe_update_temperature()