/*
* os_linux.cpp
*
- * Home page of code is: http://smartmontools.sourceforge.net
+ * Home page of code is: http://www.smartmontools.org
*
- * Copyright (C) 2003-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2003-11 Bruce Allen
* Copyright (C) 2003-11 Doug Gilbert <dgilbert@interlog.com>
- * Copyright (C) 2008-14 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-15 Christian Franke
*
* Original AACRaid code:
* Copyright (C) 2014 Raghava Aditya <raghava.aditya@pmcs.com>
#define ARGUSED(x) ((void)(x))
-const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3900 2014-05-01 17:08:59Z chrfranke $"
+const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 4157 2015-10-20 16:03:57Z chrfranke $"
OS_LINUX_H_CVSID;
extern unsigned char failuretest_permissive;
// examples for smartctl
static const char smartctl_examples[] =
"=================================================== SMARTCTL EXAMPLES =====\n\n"
- " smartctl --all /dev/hda (Prints all SMART information)\n\n"
- " smartctl --smart=on --offlineauto=on --saveauto=on /dev/hda\n"
+ " smartctl --all /dev/sda (Prints all SMART information)\n\n"
+ " smartctl --smart=on --offlineauto=on --saveauto=on /dev/sda\n"
" (Enables SMART on first disk)\n\n"
- " smartctl --test=long /dev/hda (Executes extended disk self-test)\n\n"
- " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hda\n"
+ " smartctl --test=long /dev/sda (Executes extended disk self-test)\n\n"
+ " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/sda\n"
" (Prints Self-Test & Attribute errors)\n"
" smartctl --all --device=3ware,2 /dev/sda\n"
" smartctl --all --device=3ware,2 /dev/twe0\n"
unsigned char task[sizeof(ide_task_request_t)+512];
ide_task_request_t *reqtask=(ide_task_request_t *) task;
task_struct_t *taskfile=(task_struct_t *) reqtask->io_ports;
- int retval;
memset(task, 0, sizeof(task));
// copy user data into the task request structure
memcpy(task+sizeof(ide_task_request_t), data, 512);
- if ((retval=ioctl(get_fd(), HDIO_DRIVE_TASKFILE, task))) {
- if (retval==-EINVAL)
+ if (ioctl(get_fd(), HDIO_DRIVE_TASKFILE, task)) {
+ if (errno==-EINVAL)
pout("Kernel lacks HDIO_DRIVE_TASKFILE support; compile kernel with CONFIG_IDE_TASKFILE_IO set\n");
return -1;
}
// There are two different types of ioctls(). The HDIO_DRIVE_TASK
// one is this:
if (command==STATUS_CHECK || command==AUTOSAVE || command==AUTO_OFFLINE){
- int retval;
-
// NOT DOCUMENTED in /usr/src/linux/include/linux/hdreg.h. You
// have to read the IDE driver source code. Sigh.
// buff[0]: ATA COMMAND CODE REGISTER
buff[4]=normal_lo;
buff[5]=normal_hi;
- if ((retval=ioctl(get_fd(), HDIO_DRIVE_TASK, buff))) {
- if (retval==-EINVAL) {
+ if (ioctl(get_fd(), HDIO_DRIVE_TASK, buff)) {
+ if (errno==-EINVAL) {
pout("Error SMART Status command via HDIO_DRIVE_TASK failed");
pout("Rebuild older linux 2.2 kernels with HDIO_DRIVE_TASK support added\n");
}
uint8_t aBuff[sizeof(user_aac_srb64) + sizeof(user_aac_reply)] = {0,};
pSrb = (user_aac_srb64*)aBuff;
- pReply = (user_aac_reply*)(aBuff+sizeof(user_aac_srb64));
+ pSrb->count = sizeof(user_aac_srb64) - sizeof(user_sgentry64);
#elif defined(ENVIRONMENT32)
//Create user 32 bit request
uint8_t aBuff[sizeof(user_aac_srb32) + sizeof(user_aac_reply)] = {0,};
pSrb = (user_aac_srb32*)aBuff;
- pReply = (user_aac_reply*)(aBuff+sizeof(user_aac_srb32));
-
+ pSrb->count = sizeof(user_aac_srb32) - sizeof(user_sgentry32);
#endif
pSrb->function = SRB_FUNCTION_EXECUTE_SCSI;
pSrb->sg64.sg64[0].addr64.hi32 = ((intptr_t)iop->dxferp) >> 32;
pSrb->sg64.sg64[0].length = (uint32_t)iop->dxfer_len;
- pSrb->count = sizeof(user_aac_srb64) +
- (sizeof(user_sgentry64)*(pSrb->sg64.count-1));
+ pSrb->count += pSrb->sg64.count * sizeof(user_sgentry64);
#elif defined(ENVIRONMENT32)
pSrb->sg32.count = 1;
pSrb->sg32.sg32[0].addr32 = (intptr_t)iop->dxferp;
pSrb->sg32.sg32[0].length = (uint32_t)iop->dxfer_len;
- pSrb->count = sizeof(user_aac_srb32) +
- (sizeof(user_sgentry32)*(pSrb->sg32.count-1));
+ pSrb->count += pSrb->sg32.count * sizeof(user_sgentry32);
#endif
}
+ pReply = (user_aac_reply*)(aBuff+pSrb->count);
+
memcpy(pSrb->cdb,iop->cmnd,iop->cmnd_len);
int rc = 0;
errno = 0;
rc = ioctl(get_fd(),FSACTL_SEND_RAW_SRB,pSrb);
- if(rc!= 0 || pReply->srb_status != 0x01) {
- if(pReply->srb_status == 0x08) {
- return set_err(EIO, "aacraid: Device %d %d does not exist\n" ,aLun,aId );
- }
- return set_err((errno ? errno : EIO), "aacraid result: %d.%d = %d/%d",
- aLun, aId, errno,
- pReply->srb_status);
+
+ if (rc != 0)
+ return set_err(errno, "aacraid send_raw_srb: %d.%d = %s",
+ aLun, aId, strerror(errno));
+
+/* see kernel aacraid.h and MSDN SCSI_REQUEST_BLOCK documentation */
+#define SRB_STATUS_SUCCESS 0x1
+#define SRB_STATUS_ERROR 0x4
+#define SRB_STATUS_NO_DEVICE 0x08
+#define SRB_STATUS_SELECTION_TIMEOUT 0x0a
+#define SRB_STATUS_AUTOSENSE_VALID 0x80
+
+ iop->scsi_status = pReply->scsi_status;
+
+ if (pReply->srb_status == (SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_ERROR)
+ && iop->scsi_status == SCSI_STATUS_CHECK_CONDITION) {
+ memcpy(iop->sensep, pReply->sense_data, pReply->sense_data_size);
+ iop->resp_sense_len = pReply->sense_data_size;
+ return true; /* request completed with sense data */
+ }
+
+ switch (pReply->srb_status & 0x3f) {
+
+ case SRB_STATUS_SUCCESS:
+ return true; /* request completed successfully */
+
+ case SRB_STATUS_NO_DEVICE:
+ return set_err(EIO, "aacraid: Device %d %d does not exist", aLun, aId);
+
+ case SRB_STATUS_SELECTION_TIMEOUT:
+ return set_err(EIO, "aacraid: Device %d %d not responding", aLun, aId);
+
+ default:
+ return set_err(EIO, "aacraid result: %d.%d = 0x%x",
+ aLun, aId, pReply->srb_status);
}
- return true;
}
int mjr;
int report = scsi_debugmode;
- if(sscanf(get_dev_name(),"/dev/bus/%d", &m_hba) == 0) {
+ if (sscanf(get_dev_name(), "/dev/bus/%u", &m_hba) == 0) {
if (!linux_smart_device::open())
return false;
/* Get device HBA */
{
struct megasas_pthru_frame *pthru;
struct megasas_iocpacket uio;
- int rc;
memset(&uio, 0, sizeof(uio));
pthru = &uio.frame.pthru;
uio.sgl[0].iov_len = dataLen;
}
- rc = 0;
errno = 0;
- rc = ioctl(m_fd, MEGASAS_IOC_FIRMWARE, &uio);
+ int rc = ioctl(m_fd, MEGASAS_IOC_FIRMWARE, &uio);
if (pthru->cmd_status || rc != 0) {
if (pthru->cmd_status == 12) {
return set_err(EIO, "megasas_cmd: Device %d does not exist\n", m_disknum);
smart_device * linux_areca_ata_device::autodetect_open()
{
- int is_ata = 1;
-
// autodetect device type
- is_ata = arcmsr_get_dev_type();
+ int is_ata = arcmsr_get_dev_type();
if(is_ata < 0)
{
set_err(EIO);
}
// we are going to take advantage of the fact that Linux's devfs will only
-// have device entries for devices that exist. So if we get the equivalent of
-// ls /dev/hd[a-t], we have all the ATA devices on the system
+// have device entries for devices that exist.
bool linux_smart_interface::get_dev_list(smart_device_list & devlist,
const char * pattern, bool scan_ata, bool scan_scsi,
const char * req_type, bool autodetect)
return false;
// getting bus numbers with megasas devices
- struct dirent *ep;
- unsigned int host_no = 0;
- char sysfsdir[256];
-
- /* we are using sysfs to get list of all scsi hosts */
+ // we are using sysfs to get list of all scsi hosts
DIR * dp = opendir ("/sys/class/scsi_host/");
if (dp != NULL)
{
+ struct dirent *ep;
while ((ep = readdir (dp)) != NULL) {
- if (!sscanf(ep->d_name, "host%d", &host_no))
+ unsigned int host_no = 0;
+ if (!sscanf(ep->d_name, "host%u", &host_no))
continue;
/* proc_name should be megaraid_sas */
+ char sysfsdir[256];
snprintf(sysfsdir, sizeof(sysfsdir) - 1,
- "/sys/class/scsi_host/host%d/proc_name", host_no);
+ "/sys/class/scsi_host/host%u/proc_name", host_no);
if((fp = fopen(sysfsdir, "r")) == NULL)
continue;
if(fgets(line, sizeof(line), fp) != NULL && !strncmp(line,"megaraid_sas",12)) {
}
int r = ioctl(fd, MEGASAS_IOC_FIRMWARE, &ioc);
+ ::close(fd);
if (r < 0) {
return (r);
}
*/
megasas_pd_list * list = 0;
for (unsigned list_size = 1024; ; ) {
- list = (megasas_pd_list *)realloc(list, list_size);
+ list = reinterpret_cast<megasas_pd_list *>(realloc(list, list_size));
if (!list)
throw std::bad_alloc();
bzero(list, list_size);
}
//aacraid?
- unsigned int device;
- unsigned int host;
- if(sscanf(type, "aacraid,%d,%d,%d", &host, &channel, &device)==3) {
+ unsigned host, chan, device;
+ if (sscanf(type, "aacraid,%u,%u,%u", &host, &chan, &device) == 3) {
//return new linux_aacraid_device(this,name,channel,device);
return get_sat_device("sat,auto",
- new linux_aacraid_device(this, name, host, channel, device));
+ new linux_aacraid_device(this, name, host, chan, device));
}