/*
* os_solaris.c
*
- * Home page of code is: http://smartmontools.sourceforge.net
+ * Home page of code is: http://www.smartmontools.org
*
- * Copyright (C) 2003-6 SAWADA Keiji <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2003-6 Casper Dik <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2003-08 SAWADA Keiji
+ * Copyright (C) 2003-15 Casper Dik
*
* 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
* any later version.
*
* You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
extern long long bytes;
-static const char *filenameandversion="$Id: os_solaris.cpp,v 1.28 2006/08/25 06:06:25 sxzzsf Exp $";
+static const char *filenameandversion="$Id: os_solaris.cpp 4142 2015-10-14 19:05:19Z chrfranke $";
-const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp,v 1.28 2006/08/25 06:06:25 sxzzsf Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp 4142 2015-10-14 19:05:19Z chrfranke $" \
ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_SOLARIS_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// The printwarning() function warns about unimplemented functions
static const char *uscsidrvrs[] = {
"sd",
"ssd",
+ "disk", // SATA devices
"st"
};
return close(fd);
}
-#if defined(__sparc)
+#if defined(WITH_SOLARIS_SPARC_ATA)
// swap each 2-byte pairs in a sector
static void swap_sector(void *p)
{
#endif
// Interface to ATA devices. See os_linux.c
-int marvell_command_interface(int fd, smart_command_set command, int select, char *data){
- ARGUSED(fd); ARGUSED(command); ARGUSED(select); ARGUSED(data);
- return -1;
-}
-
-int highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
-{
- ARGUSED(fd); ARGUSED(command); ARGUSED(select); ARGUSED(data);
- return -1;
-}
-
int ata_command_interface(int fd, smart_command_set command, int select, char *data){
-#if defined(__sparc)
+#if defined(WITH_SOLARIS_SPARC_ATA)
int err;
switch (command){
return smart_status_check(fd);
default:
pout("Unrecognized command %d in ata_command_interface() of os_solaris.c\n", command);
- exit(1);
+ EXIT(1);
break;
}
-#else /* __sparc */
+#else /* WITH_SOLARIS_SPARC_ATA */
ARGUSED(fd); ARGUSED(command); ARGUSED(select); ARGUSED(data);
/* Above smart_* routines uses undocumented ioctls of "dada"
return -1;
}
-// Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
-int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data){
- ARGUSED(fd); ARGUSED(disknum); ARGUSED(escalade_type);
- ARGUSED(command); ARGUSED(select); ARGUSED(data);
-
- if (printwarning(1))
- return -1;
- return -1;
-}
-
#include <errno.h>
#include <sys/scsi/generic/commands.h>
#include <sys/scsi/generic/status.h>
#include <sys/scsi/impl/uscsi.h>
// Interface to SCSI devices. See os_linux.c
-int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) {
+int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
+{
struct uscsi_cmd uscsi;
- if (report > 0) {
- int k;
- const unsigned char * ucp = iop->cmnd;
- const char * np;
-
- np = scsi_get_opcode_name(ucp[0]);
- pout(" [%s: ", np ? np : "<unknown opcode>");
- for (k = 0; k < (int)iop->cmnd_len; ++k)
- pout("%02x ", ucp[k]);
- if ((report > 1) &&
- (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
- int trunc = (iop->dxfer_len > 256) ? 1 : 0;
-
- pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
- (trunc ? " [only first 256 bytes shown]" : ""));
- dStrHex((char *)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
- }
- else
- pout("]");
+ if (report > 0) {
+ int k;
+ const unsigned char * ucp = iop->cmnd;
+ const char * np;
+
+ np = scsi_get_opcode_name(ucp[0]);
+ pout(" [%s: ", np ? np : "<unknown opcode>");
+ for (k = 0; k < (int)iop->cmnd_len; ++k)
+ pout("%02x ", ucp[k]);
+ pout("]\n");
+ if ((report > 1) &&
+ (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
+ int trunc = (iop->dxfer_len > 256) ? 1 : 0;
+
+ pout(" Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
+ (trunc ? " [only first 256 bytes shown]" : ""));
+ dStrHex((char *)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
-
-
+ }
memset(&uscsi, 0, sizeof (uscsi));
uscsi.uscsi_cdb = reinterpret_cast<char*>(iop->cmnd);
uscsi.uscsi_cdblen = iop->cmnd_len;
if (iop->timeout == 0)
- uscsi.uscsi_timeout = 60; /* XXX */
+ uscsi.uscsi_timeout = 60; /* 60 seconds */
else
uscsi.uscsi_timeout = iop->timeout;
uscsi.uscsi_bufaddr = reinterpret_cast<char*>(iop->dxferp);
default:
return -EINVAL;
}
- uscsi.uscsi_flags |= USCSI_ISOLATE;
+ uscsi.uscsi_flags |= (USCSI_ISOLATE | USCSI_RQENABLE | USCSI_SILENT);
+
+ if (ioctl(fd, USCSICMD, &uscsi)) {
+ int err = errno;
- if (ioctl(fd, USCSICMD, &uscsi))
- return -errno;
+ if (! ((EIO == err) && uscsi.uscsi_status))
+ return -err;
+ /* errno is set to EIO when a non-zero SCSI completion status given */
+ }
iop->scsi_status = uscsi.uscsi_status;
iop->resid = uscsi.uscsi_resid;
iop->resp_sense_len = iop->max_sense_len - uscsi.uscsi_rqresid;
if (report > 0) {
- int trunc = (iop->dxfer_len > 256) ? 1 : 0;
- pout(" status=0\n");
-
- pout(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
- (trunc ? " [only first 256 bytes shown]" : ""));
- dStrHex((char *)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
+ int trunc;
+ int len = iop->resp_sense_len;
+
+ if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) &&
+ iop->sensep && (len > 3)) {
+ if ((iop->sensep[0] & 0x7f) > 0x71)
+ pout(" status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",
+ iop->scsi_status, iop->sensep[1] & 0xf,
+ iop->sensep[2], iop->sensep[3]);
+ else
+ pout(" status=%x: sense_key=%x asc=%x ascq=%x\n",
+ iop->scsi_status, iop->sensep[2] & 0xf,
+ iop->sensep[12], iop->sensep[13]);
+ if (report > 1) {
+ pout(" >>> Sense buffer, len=%d:\n", len);
+ dStrHex((const char *)iop->sensep, ((len > 252) ? 252 : len) , 1);
+ }
+ } else if (iop->scsi_status)
+ pout(" status=%x\n", iop->scsi_status);
+ if (iop->resid)
+ pout(" dxfer_len=%d, resid=%d\n", iop->dxfer_len, iop->resid);
+ if (report > 1) {
+ len = iop->dxfer_len - iop->resid;
+ if (len > 0) {
+ trunc = (len > 256) ? 1 : 0;
+ pout(" Incoming data, len=%d%s:\n", len,
+ (trunc ? " [only first 256 bytes shown]" : ""));
+ dStrHex((char *)iop->dxferp, (trunc ? 256 : len) , 1);
+ }
+ }
}
-
- return (0);
+ return 0;
}