mirror of
https://github.com/martijnvanbrummelen/nwipe.git
synced 2026-02-20 13:42:14 +00:00
included hddtemp code for SCSI disk temperatures
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
137
src/hddtemp_scsi/get_scsi_temp.c
Normal file
137
src/hddtemp_scsi/get_scsi_temp.c
Normal 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
102
src/hddtemp_scsi/hddtemp.h
Normal 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
153
src/hddtemp_scsi/scsi.c
Normal 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
24
src/hddtemp_scsi/scsi.h
Normal 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
221
src/hddtemp_scsi/scsicmds.c
Normal 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;
|
||||
}
|
||||
|
||||
36
src/hddtemp_scsi/scsicmds.h
Normal file
36
src/hddtemp_scsi/scsicmds.h
Normal 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
|
||||
@@ -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" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user